/*
题目: 等式方程的可满足性
给定一个由表示变量之间关系的字符串方程组成的数组，每个字符串方程 equations[i] 的长度为 4，并采用两种不同的形式之一："a==b" 或 "a!=b"。在这里，a 和 b 是小写字母（不一定不同），表示单字母变量名。

只有当可以将整数分配给变量名，以便满足所有给定的方程时才返回 true，否则返回 false。
https://leetcode.cn/problems/satisfiability-of-equality-equations/description/
 */
public class EquationsPossible {
    int[] fa = new int[26];

    public boolean equationsPossible(String[] equations) {
        Arrays.fill(fa, -1);
        // 相等的归入集合, 记录哪些字母是不相等的, 如果集合中存在不相等的, 就 FALSE
        List<Integer>[] group = new List[26];
        for (int i = 0; i < 26; i ++)
            group[i] = new ArrayList<> ();

        for (String exp : equations) {
            if (exp.charAt(1) == '!') { // 不相等
                if (exp.charAt(0) == exp.charAt(3)) return false; // 特殊处理一下
                group[exp.charAt(0) - 'a'].add(exp.charAt(3) - 'a');
            } else {
                unit(exp.charAt(0) - 'a', exp.charAt(3) - 'a');
            }
        }

        for (int i = 0; i < 26; i ++) {
            for (int j = 0; j < group[i].size(); j ++) {
                if (isConnected(i, group[i].get(j))) {
                    return false;
                }
            }
        }

        return true;
    }

    private int root(int x) {
        return fa[x] >= 0 ? root(fa[x]) : x;
    }

    private void unit(int x, int y) {
        if (x == y) return ;
        int i = root(x), j = root(y);
        if (i == j) return ;

        fa[i] += fa[j];
        fa[j] = i;
    }

    private boolean isConnected(int x, int y) {
        if (x == y) return false;
        return root(x) == root(y);
    }
}
